#include "applyfriend.h"
#include "ui_applyfriend.h"
#include "usermanager.h"
#include "tcpmanager.h"

#include <QJsonDocument>
#include <QJsonObject>
#include <QScrollBar>
#include <QDebug>

ApplyFriend::ApplyFriend(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::ApplyFriend)
    , m_label_point(2, 6)
{
    ui->setupUi(this);

    setWindowFlags(windowFlags() | Qt::FramelessWindowHint);

    this->setObjectName("ApplyFriend");
    this->setModal(true);
    ui->name_edit->setPlaceholderText(tr("筱"));
    ui->lb_edit->setPlaceholderText("搜索、添加标签");
    ui->backname_edit->setPlaceholderText("Xiao");

    ui->lb_edit->SetMaxLength(21);
    ui->lb_edit->move(2, 2);
    ui->lb_edit->setFixedHeight(20);
    ui->lb_edit->setMaxLength(10);
    ui->input_tip_wid->hide();

    m_tip_cur_point = QPoint(5, 5);
    // TODO 测试数据
    m_tip_data = { "同学","家人","菜鸟教程","C++ Primer","Rust 程序设计",
                  "父与子学Python","nodejs开发指南","go 语言开发指南",
                  "游戏伙伴","金融投资","微信读书","拼多多拼友" };
    // 连接更多便签的信号
    connect(ui->more_lb, &ClickedOnceLabel::clicked, this, &ApplyFriend::showMoreLabel);
    initTipLbs();

    // 连接输入便签的回车事件
    connect(ui->lb_edit, &CustomizeEdit::returnPressed, this, &ApplyFriend::SlotLabelEnter);
    // 连接输入便签改变的信号
    connect(ui->lb_edit, &CustomizeEdit::textChanged, this, &ApplyFriend::SlotLabelTextChange);
    connect(ui->lb_edit, &CustomizeEdit::editingFinished, this, &ApplyFriend::SlotLabelEditFinished);
    // 连接便签添加的信号
    connect(ui->tip_lb, &ClickedOnceLabel::clicked, this, &ApplyFriend::SlotAddFriendLabelByClickTip);

    ui->scrollArea->horizontalScrollBar()->setHidden(true);
    ui->scrollArea->verticalScrollBar()->setHidden(true);
    ui->scrollArea->installEventFilter(this);
    ui->sure_btn->setState("normal", "hover", "press");
    ui->cancel_btn->setState("normal", "hover", "press");

    // 连接确认和取消按钮的槽函数
    connect(ui->cancel_btn, &QPushButton::clicked, this, &ApplyFriend::SlotApplyCancel);
    connect(ui->sure_btn, &QPushButton::clicked, this, &ApplyFriend::SlotApplySure);
}

ApplyFriend::~ApplyFriend()
{
    qDebug() << "ApplyFriend destruct";
    delete ui;
}

void ApplyFriend::initTipLbs()
{
    int lines = 1;
    for (int i = 0; i < m_tip_data.size(); ++ i) {
        auto* lb = new ClickedLabel(ui->lb_list);
        lb->setState("normal", "hover", "pressed", "selected_normal",
                     "selected_hover", "selected_pressed");
        lb->setObjectName("tipslb");
        lb->setText(m_tip_data[i]);

        connect(lb, &ClickedLabel::clicked, this, &ApplyFriend::SlotChangeFriendLabelByTip);

        QFontMetrics fontMetrics(lb->font()); // 获取QLabel控件的字体信息
        // 获取便签文本的宽度
        int text_width = 0;
        for (int i = 0; i < lb->text().length(); ++i) {
            text_width += fontMetrics.horizontalAdvance(lb->text().at(i));
        }
        int text_height = fontMetrics.height(); // 获取文本的高度

        // 超出便签显示窗口的宽度，则需要换行
        if ( m_tip_cur_point.x() + text_width + tip_offset > ui->lb_list->width() ) {
            ++ lines;
            if (lines > 2) {
                delete lb;
                return ;
            }

            m_tip_cur_point.setX(tip_offset);
            m_tip_cur_point.setY(m_tip_cur_point.y() + text_height + 15);
        }

        auto next_point = m_tip_cur_point;
        addTipLbs(lb, m_tip_cur_point, next_point, text_width, text_height);
        m_tip_cur_point = next_point;
    }
}

void ApplyFriend::addTipLbs(ClickedLabel* lb, QPoint cur_point, QPoint& next_point, int text_width, int text_height)
{
    lb->move(cur_point);
    lb->show();
    m_add_labels.insert(lb->text(), lb);
    m_add_label_keys.push_back(lb->text());
    next_point.setX(lb->pos().x() + text_width + 15);
    next_point.setY(lb->pos().y());
}

void ApplyFriend::setSearchInfo(std::shared_ptr<SearchInfo> sinfo)
{
    m_sinfo = sinfo;
    auto applyname = UserManager::getInstance()->getName();
    auto backname = sinfo->m_name;
    ui->name_edit->setText(applyname);
    ui->backname_edit->setText(backname);
}

bool ApplyFriend::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == ui->scrollArea && event->type() == QEvent::Enter) {
        ui->scrollArea->verticalScrollBar()->setHidden(false);
    } else if (obj == ui->scrollArea && event->type() == QEvent::Leave) {
        ui->scrollArea->verticalScrollBar()->setHidden(true);
    }
    
    return QObject::eventFilter(obj, event);
}

// 重新排列好友标签编辑栏的标签
void ApplyFriend::resetLabels()
{
    auto max_width = ui->grid_wid->width();
    auto label_height = 0;
    for (auto it = m_friend_labels.begin(); it != m_friend_labels.end(); ++ it) {
        // TODO: 添加便签宽度统计
        // 超出显示区域的最大宽度
        if (m_label_point.x() + it.value()->width() > max_width) {
            m_label_point.setY(m_label_point.y() + it.value()->height() + 6);
            m_label_point.setX(2);
        }

        it.value()->move(m_label_point);
        it.value()->show();

        m_label_point.setX(m_label_point.x() + it.value()->width() + 2);
        m_label_point.setY(m_label_point.y());
        label_height = it.value()->height();
    }

    if (m_friend_labels.isEmpty()) {
        ui->lb_edit->move(m_label_point);
        return ;
    }

    if (m_label_point.x() + MIN_APPLY_LABEL_ED_LEN > ui->grid_wid->width()) {
        ui->lb_edit->move(2, m_label_point.y() + label_height + 6);
    } else {
        ui->lb_edit->move(m_label_point);
    }
}

void ApplyFriend::addLabel(QString name)
{
    if (m_friend_labels.find(name) != m_friend_labels.end()) {
        ui->lb_edit->clear();
        return ;
    }

    auto tmplabel = new FriendLabel(ui->grid_wid);
    tmplabel->SetText(name);
    tmplabel->setObjectName("FriendLabel");

    auto max_width = ui->grid_wid->width();
    // TODO : 添加宽度统计
    if (m_label_point.x() + tmplabel->width() > max_width) {
        // 换行
        m_label_point.setY(m_label_point.y() + tmplabel->height() + 6);
        m_label_point.setX(2);
    } else {
        // ＴＯＤＯ:
    }

    tmplabel->move(m_label_point);
    tmplabel->show();
    m_friend_labels[tmplabel->Text()] = tmplabel;
    m_friend_label_keys.push_back(tmplabel->Text());

    connect(tmplabel, &FriendLabel::sig_close, this, &ApplyFriend::SlotRemoveFriendLabel);

    m_label_point.setX(m_label_point.x() + tmplabel->width() + 2);

    if (m_label_point.x() + MIN_APPLY_LABEL_ED_LEN > ui->grid_wid->width()) {
        ui->lb_edit->move(2, m_label_point.y() + tmplabel->height() + 2);
    } else {
        ui->lb_edit->move(m_label_point);
    }

    ui->lb_edit->clear();

    if (ui->grid_wid->height() < m_label_point.y() + tmplabel->height() + 2) {
        // 扩宽编辑窗口
        ui->grid_wid->setFixedHeight(m_label_point.y() + tmplabel->height() * 2 + 2);
    }
}

// 显示更多的标签
void ApplyFriend::showMoreLabel()
{
    qDebug()<< "receive more label clicked......";
    ui->more_lb_wid->hide();
    
    ui->lb_list->setFixedWidth(325);
    m_tip_cur_point = QPoint(5, 5);
    auto next_point = m_tip_cur_point;
    int text_width;
    int text_height;
    
    // 显示所有的便签
    for (auto& added_key : m_add_label_keys) {
        auto added_lb = m_add_labels[added_key];
        
        QFontMetrics fontMetrics(added_lb->font()); // 获取便签的字体信息
        // 获取文本的宽度
        text_width = 0;
        for (int i = 0; i < added_lb->text().length(); ++i) {
            text_width += fontMetrics.horizontalAdvance(added_lb->text().at(i));
        }
        text_height = fontMetrics.height(); // 获取文本的高度

        if(m_tip_cur_point.x() + text_width + tip_offset > ui->lb_list->width()){
            m_tip_cur_point.setX(tip_offset);
            m_tip_cur_point.setY(m_tip_cur_point.y() + text_height + 15);
        }
        added_lb->move(m_tip_cur_point);

        next_point.setX(added_lb->pos().x() + text_width + 15);
        next_point.setY(m_tip_cur_point.y());

        m_tip_cur_point = next_point;
    }

    // 添加未显示完的便签
    for(int i = 0; i < m_tip_data.size(); ++ i){
        auto iter = m_add_labels.find(m_tip_data[i]);
        if(iter != m_add_labels.end()){
            continue;
        }

        auto* lb = new ClickedLabel(ui->lb_list);
        lb->setState("normal", "hover", "pressed", "selected_normal",
                     "selected_hover", "selected_pressed");
        lb->setObjectName("tipslb");
        lb->setText(m_tip_data[i]);
        connect(lb, &ClickedLabel::clicked, this, &ApplyFriend::SlotChangeFriendLabelByTip);

        QFontMetrics fontMetrics(lb->font()); // 获取QLabel控件的字体信息
        int textWidth = 0; // 获取文本的宽度
        for (int i = 0; i < lb->text().length(); ++i) {
            textWidth += fontMetrics.horizontalAdvance(lb->text().at(i));
        }
        int textHeight = fontMetrics.height(); // 获取文本的高度

        if (m_tip_cur_point.x() + textWidth + tip_offset > ui->lb_list->width()) {

            m_tip_cur_point.setX(tip_offset);
            m_tip_cur_point.setY(m_tip_cur_point.y() + textHeight + 15);

        }

        next_point = m_tip_cur_point;

        addTipLbs(lb, m_tip_cur_point, next_point, textWidth, textHeight);

        m_tip_cur_point = next_point;
    }

    int diff_height = next_point.y() + text_height + tip_offset - ui->lb_list->height();
    ui->lb_list->setFixedHeight(next_point.y() + text_height + tip_offset);
    // if (diff_height > 0) {
    //     ui->lb_list->setFixedHeight(next_point.y() + text_height + tip_offset);
    // }

    qDebug() <<"after resize ui->lb_list size is " <<  ui->lb_list->size();
    ui->scrollAreaWidgetContents->setFixedHeight(ui->scrollAreaWidgetContents->height() + diff_height);
}

// 输入label，按下回车触发，将标签加入到展示栏
void ApplyFriend::SlotLabelEnter()
{
    if (ui->lb_edit->text().isEmpty()){
        return;
    }

    auto text = ui->lb_edit->text();

    addLabel(ui->lb_edit->text());

    ui->input_tip_wid->hide();

    auto find_it = std::find(m_tip_data.begin(), m_tip_data.end(), text);
    // 找到了就只需设置状态为选中即可
    if (find_it == m_tip_data.end()) {
       m_tip_data.push_back(text);
    }

    //判断标签展示栏是否有该标签
    auto find_add = m_add_labels.find(text);
    if (find_add != m_add_labels.end()) {
        find_add.value()->setCurState(ClickLbState::Selected);
        return;
    }

    // 标签展示栏也增加一个标签, 并设置绿色选中
    auto* lb = new ClickedLabel(ui->lb_list);
    lb->setState("normal", "hover", "pressed", "selected_normal",
                 "selected_hover", "selected_pressed");
    lb->setObjectName("tipslb");
    lb->setText(text);
    connect(lb, &ClickedLabel::clicked, this, &ApplyFriend::SlotChangeFriendLabelByTip);
    qDebug() << "ui->lb_list->width() is " << ui->lb_list->width();
    qDebug() << "m_tip_cur_point.x() is " << m_tip_cur_point.x();

    QFontMetrics fontMetrics(lb->font()); // 获取QLabel控件的字体信息
    // 获取文本的宽度
    int textWidth = 0;
    for (int i = 0; i < lb->text().length(); ++i) {
        textWidth += fontMetrics.horizontalAdvance(lb->text().at(i));
    }
    int textHeight = fontMetrics.height(); // 获取文本的高度
    qDebug() << "textWidth is " << textWidth;

    if (m_tip_cur_point.x() + textWidth + tip_offset + 3 > ui->lb_list->width()) {
        m_tip_cur_point.setX(5);
        m_tip_cur_point.setY(m_tip_cur_point.y() + textHeight + 15);
    }

    auto next_point = m_tip_cur_point;

    addTipLbs(lb, m_tip_cur_point, next_point, textWidth, textHeight);
    m_tip_cur_point = next_point;

    int diff_height = next_point.y() + textHeight + tip_offset - ui->lb_list->height();
    ui->lb_list->setFixedHeight(next_point.y() + textHeight + tip_offset);
    // if (diff_height > 0) {
    //     ui->lb_list->setFixedHeight(next_point.y() + textHeight + tip_offset);
    // }

    lb->setCurState(ClickLbState::Selected);
    ui->scrollAreaWidgetContents->setFixedHeight(ui->scrollAreaWidgetContents->height() + diff_height);
}

// 点击关闭，移除展示栏中的好友便签
void ApplyFriend::SlotRemoveFriendLabel(QString name)
{
    qDebug() << "receive close signal";

    m_label_point.setX(2);
    m_label_point.setY(6);

    auto find_iter = m_friend_labels.find(name);

    if (find_iter == m_friend_labels.end()){
        return;
    }

    auto find_key = m_friend_label_keys.end();
    for (auto iter = m_friend_label_keys.begin(); iter != m_friend_label_keys.end(); iter++) {
        if (*iter == name) {
            find_key = iter;
            break;
        }
    }

    if ( find_key != m_friend_label_keys.end() ) {
        m_friend_label_keys.erase(find_key);
    }


    delete find_iter.value();

    m_friend_labels.erase(find_iter);

    resetLabels();

    auto find_add = m_add_labels.find(name);
    if( find_add == m_add_labels.end() ){
        return;
    }

    find_add.value()->resetNormalState();
}

// 通过点击tip实现增加和删除好友的便签
void ApplyFriend::SlotChangeFriendLabelByTip(QString lb_text, ClickLbState state)
{
    auto find_iter = m_add_labels.find(lb_text);
    if ( find_iter == m_add_labels.end() ){
        return;
    }

    if (state == ClickLbState::Selected){
        //编写添加逻辑
        addLabel(lb_text);
        return;
    }

    if (state == ClickLbState::Normal) {
        //编写删除逻辑
        SlotRemoveFriendLabel(lb_text);
        return;
    }
}

// 输入框文本变换显示不同提示
void ApplyFriend::SlotLabelTextChange(const QString &text)
{
    if (text.isEmpty()) {
        ui->tip_lb->setText("");
        ui->input_tip_wid->hide();
        return;
    }

    auto iter = std::find(m_tip_data.begin(), m_tip_data.end(), text);
    if (iter == m_tip_data.end()) {
        auto new_text = add_prefix + text;
        ui->tip_lb->setText(new_text);
        ui->input_tip_wid->show();
        return;
    }
    ui->tip_lb->setText(text);
    ui->input_tip_wid->show();
}

// 在输入框的输入已完成
void ApplyFriend::SlotLabelEditFinished()
{
    ui->input_tip_wid->hide();
}

// 输入标签显示提示框，点击提示框内容后添加好友便签
void ApplyFriend::SlotAddFriendLabelByClickTip(QString text)
{
    int index = text.indexOf(add_prefix);
    if (index != -1) {
        text = text.mid(index + add_prefix.length());
    }
    addLabel(text);

    auto find_it = std::find(m_tip_data.begin(), m_tip_data.end(), text);
    // 找到了就只需设置状态为选中即可
    if (find_it == m_tip_data.end()) {
        m_tip_data.push_back(text);
    }

    // 判断标签展示栏是否有该标签
    auto find_add = m_add_labels.find(text);
    if ( find_add != m_add_labels.end() ) {
        find_add.value()->setCurState(ClickLbState::Selected);
        return;
    }

    // 标签展示栏也增加一个标签, 并设置绿色选中
    auto* lb = new ClickedLabel(ui->lb_list);
    lb->setState("normal", "hover", "pressed", "selected_normal",
                 "selected_hover", "selected_pressed");
    lb->setObjectName("tipslb");
    lb->setText(text);
    connect(lb, &ClickedLabel::clicked, this, &ApplyFriend::SlotChangeFriendLabelByTip);
    qDebug() << "ui->lb_list->width() is " << ui->lb_list->width();
    qDebug() << "m_tip_cur_point.x() is " << m_tip_cur_point.x();

    QFontMetrics fontMetrics(lb->font()); // 获取QLabel控件的字体信息
    // 获取文本的宽度
    int textWidth = 0;
    for (int i = 0; i < lb->text().length(); ++i) {
        textWidth += fontMetrics.horizontalAdvance(lb->text().at(i));
    }
    int textHeight = fontMetrics.height(); // 获取文本的高度
    qDebug() << "textWidth is " << textWidth;

    if (m_tip_cur_point.x() + textWidth + tip_offset + 3 > ui->lb_list->width()) {
        m_tip_cur_point.setX(5);
        m_tip_cur_point.setY(m_tip_cur_point.y() + textHeight + 15);
    }

    auto next_point = m_tip_cur_point;

    addTipLbs(lb, m_tip_cur_point, next_point, textWidth, textHeight);
    m_tip_cur_point = next_point;

    int diff_height = next_point.y() + textHeight + tip_offset - ui->lb_list->height();
    ui->lb_list->setFixedHeight(next_point.y() + textHeight + tip_offset);

    lb->setCurState(ClickLbState::Selected);

    ui->scrollAreaWidgetContents->setFixedHeight(ui->scrollAreaWidgetContents->height() + diff_height );
}

// 处理确定添加好友的回调
void ApplyFriend::SlotApplySure()
{
    qDebug() << "Slot Apply Sure called" ;
    // 发送请求
    QJsonObject jsonObj;
    auto uid = UserManager::getInstance()->getUid();
    jsonObj["uid"] = uid;
    auto name = ui->name_edit->text();
    if (name.isEmpty()) {
        name = ui->name_edit->placeholderText();
    }

    jsonObj["applyname"] = name;

    auto backname = ui->backname_edit->text();
    if (backname.isEmpty()) {
        backname = ui->backname_edit->placeholderText();
    }

    jsonObj["backname"] = backname;
    jsonObj["touid"] = m_sinfo->m_uid;

    QJsonDocument doc(jsonObj);
    QByteArray jsonData = doc.toJson(QJsonDocument::Compact);

    // 发送tcp请求给Chatserver
    emit TcpManager::getInstance()->sig_send_data(ReqId::ID_ADD_FRIEND_REQ, jsonData);

    this->hide();
    deleteLater();
}

// 处理取消的回调
void ApplyFriend::SlotApplyCancel()
{
    qDebug() << "Slot Apply Cancel";
    this->hide();
    deleteLater();
}
